package cn.jaye.fabric.domain.service;

import cn.jaye.fabric.common.constant.Global;
import cn.jaye.fabric.common.constant.MicroConstant;
import cn.jaye.fabric.domain.model.Guess;
import cn.jaye.fabric.domain.model.History;
import cn.jaye.fabric.domain.model.Match;
import cn.jaye.fabric.infrastructure.mybatis.impl.GuessRepositoryImpl;
import cn.jaye.fabric.infrastructure.mybatis.impl.HistoryRepositoryImpl;
import cn.jaye.fabric.infrastructure.mybatis.impl.MatchRepositoryImpl;
import cn.jaye.fabric.infrastructure.mybatis.impl.UseRepositoryImpl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by Administrator on 2018/6/4.
 */
@Service
public class CalculateService {

    private Logger logger = LoggerFactory.getLogger(CalculateService.class);

    @Autowired
    private MatchRepositoryImpl matchRepository;

    @Autowired
    private GuessRepositoryImpl guessRepository;

    @Autowired
    private HistoryRepositoryImpl historyRepository;

    @Autowired
    private UseRepositoryImpl useRepository;

    @Autowired
    private MicroConstant microConstant;


    private List<Match> getMatchResult() {
        return matchRepository.selectList(new EntityWrapper<Match>()
                .eq("match_state", Global.MATCH_STATE_FINUSHED));
    }

    private List<Guess> getUserGuess(String matchId) {
        return guessRepository.selectList(new EntityWrapper<Guess>()
                .eq("state", Global.GUESS_STATE_NORMAL)
                .eq("match_id", matchId));
    }

    public void calculateResult() {
        List<Match> matchList = getMatchResult();
        History history = new History();
        for (Match match : matchList) {
            List<Guess> guessList = getUserGuess(match.getMatchId());
            if (null != guessList && guessList.size() > 0) {
                for (Guess guess : guessList) {
                    history.setUserName(guess.getUserName());
                    history.setMatchId(guess.getMatchId());
                    Integer userScore = getUserScore(match.getHostScore(), match.getGuestScore(), guess.getHostScore(), guess.getGuestScore());
                    history.setScore(userScore);
                    if (saveHistory(history)) {
                        logger.info("save history success ,username: " + guess.getUserName() + ",mathchId: " + guess.getState());
                        guess.setState(Global.GUESS_STATE_COUNTED);
                        updateUserCount(guess.getUserName(), userScore);
                        guessRepository.update(guess, new EntityWrapper<Guess>()
                                .eq("match_id", guess.getMatchId())
                                .eq("user_name", guess.getUserName())
                                .eq("state", Global.GUESS_STATE_NORMAL));
                        logger.info("update this guess state to be counted, success username: " + guess.getUserName() + ",mathchId: " + guess.getState());
                    }
                }
            } else {
                logger.info("matchId为 : " + match.getMatchId() + " ,无用户竞猜数据");
            }
            match.setMatchState(Global.MATCH_STATE_COUNTED);
            matchRepository.update(match, new EntityWrapper<Match>()
                    .eq("match_id", match.getMatchId())
                    .eq("match_state", Global.MATCH_STATE_FINUSHED));
        }
    }

    private Integer getUserScore(Integer hostScore, Integer guestScore, Integer guessHostScore, Integer guessGuestScore) {
        Integer scoreDiff = hostScore - guestScore;
        Integer guessDiff = guessHostScore - guessGuestScore;
        if (scoreDiff > 0) {
            if (guessDiff > 0) {
                return resultPoint(hostScore, guestScore, guessHostScore, guessGuestScore);
            }
        } else if (scoreDiff == 0) {
            if (guessDiff == 0) {
                return resultPoint(hostScore, guestScore, guessHostScore, guessGuestScore);
            }
        } else {
            if (guessDiff < 0) {
                return resultPoint(hostScore, guestScore, guessHostScore, guessGuestScore);
            }
        }
        return microConstant.getGuessPartInPoint();
    }

    private Integer resultPoint(Integer hostScore, Integer guestScore, Integer guessHostScore, Integer guessGuestScore) {
        if (guessHostScore.equals(hostScore) && guessGuestScore.equals(guestScore)) {
            return microConstant.getGuessRightScorePoint();
        } else {
            return microConstant.getGuessRightResultPoint();
        }
    }


    @Transactional(rollbackFor = Exception.class)
    private boolean saveHistory(History history) {
        return historyRepository.insert(history);
    }

    @Transactional(rollbackFor = Exception.class)
    private void updateUserCount(String username, Integer point) {
        if (point > 0) {
            useRepository.updateUserPoint(username, point);
        }
    }
}
